﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Gp.Scripts.Core.Skill;
using Gp.Scripts.Core.Unit;
using Gp.Scripts.Data;
using Gp.Scripts.Data.Skills;
using Gp.Scripts.Equip;
using Gp.Scripts.GUI;
using UnityEngine;

namespace Gp.Scripts.Core
{
    public class UnitAttackResultEvent
    {
        public BaseUnit Source { get; set; }
        public BaseUnit Target { get; set; }

        public AttackActionResult Result { get; }

        public UnitAttackResultEvent(BaseUnit source, BaseUnit target, AttackActionResult result)
        {
            Source = source;
            Target = target;
            Result = result;
        }
    }

    public class UnitNoSourceDamageEvent
    {
        public BaseUnit Unit;
        public DamageInfo Info;

        public UnitNoSourceDamageEvent(BaseUnit unit, DamageInfo info)
        {
            Unit = unit;
            Info = info;
        }
    }


    public class UnitHealthLostEvent
    {
        public BaseUnit Unit { get; }
        public DamageInfo DamageInfo { get; }

        public UnitHealthLostEvent(BaseUnit unit, DamageInfo damageInfo)
        {
            Unit       = unit;
            DamageInfo = damageInfo;
        }
    }


    public enum SkillFilter
    {
        Attack,
        Magic,
    }


    public abstract class BattleCommand
    {
        public abstract void OnExecute();
    }

    public abstract class BattleSequenceCommand
    {
        // todo: 添加sequence 配置类
        public abstract IEnumerator OnExecute();
    }

    /// <summary>
    /// 此系统负责全局机制的处理逻辑
    /// </summary>
    // [AutoLoad]
    public partial class BattleLogic
    {
        #region Attack

        /// <summary>
        /// 计算武器能够攻击的次数
        /// </summary>
        /// <returns></returns>
        public static int ResolveAttackFrequency(WeaponEntity weapon, BaseUnit holder)
        {
            // if (weapon.TypeCode.IsRanged()) return 1;
            // BaseBuff buff = null;
            // 如果单位处于加速状态，则能够攻击2次
            // buff?.Consume();
            // return buff != null ? 2 : 1;
            return 1;
        }


        /// <summary>
        ///  处理单位攻击结果。通常为生命值 -= 造成的伤害
        /// </summary>
        public static IEnumerator HandleAttack(BaseUnit source, BaseUnit target, AttackActionResult res)
        {
            if (IsUnitDestroyed(target)) yield break;

            // if (source.PlayerNumber != target.PlayerNumber)
            // Global.Get<BattleSystem>().Level.AddSequenceBuffer("开启战斗", TryStartBattleProcess());


            // 消耗 buff
            // foreach (var buff in res.BuffConsume) {
            //     res.Log("消耗buff：" + buff.EntityConfig.ItemName);
            //     buff.Consume();
            // }

            Debug.Log(res.Log());
            //todo : 添加管理结构

            // 给单位施加力
            var power = 0;
            // // 攻击方向
            // var attackDirection =
            //     (source.transform.position - target.transform.position).normalized *
            //     power; // 或者是source.transform.forward;

            var e = new UnitAttackResultEvent(source, target, res);
            // 发送事件
            Global.SendEvent(e);
            // BattleMessageHandler.Interface.SendEvent(e);

            // 如果未命中
            if (!res.IsHit) yield break;


            // target.ReceiveImpose(attackDirection);
            target.Model.GestureTrigger(new HitGestureTrigger((target.transform.position - source.transform.position).normalized));
            // ============================= 数值处理 ====================================


            // 处理单位护甲
            // foreach (var infos in res.ArmorDamageInfos) {
            //     // 造成伤害
            //     infos.ExecuteDamage();
            // }


            yield return HandleHealthLost(target, new DamageInfo(res.DamageMake));
            // 当发生击杀
            if (IsUnitDestroyed(target))
            {
                HandleUnitKill(source, target);
                yield break;
            }

            // 触发格挡动画
            // target.Model.GestureTrigger(new HitGestureTrigger(attackDirection));


            // IEnumerator TryStartBattleProcess() {
            //     Global.Get<BattleSystem>().StartBattle();
            //     yield break;
            // }
        }


        public static AttackPreReaction ResolvePreAttack(BaseUnit attacker, BaseUnit target, WeaponEntity weapon,
            bool                                                  isCharging = false)
        {
            // 不含有不可阻挡标记
            return new AttackPreReaction(attacker, target, true, isCharging, weapon);
        }


        public static IEnumerator PlayAttack(BaseUnit source, BaseUnit target, AttackActionResult res,
            bool                                      accAttack = false)
        {
            // 播放攻击动画
            // if (accAttack) {
            //     yield return HandleAttackProcess(source, target, res,
            //         null);
            // }
            // else {
            // yield return source.Model.PlaySequence(new AttackGestureSequence(target,
            //     () => {
            //         if (!source) {
            //             return;
            //         }
            //
            //         Global.Get<BattleSystem>().Level.StartCoroutine(HandleAttackProcess(source, target, res,
            //             null));
            //     }));
            // }

            yield return HandleAttack(source, target, res);

            // while (!attackOver) {
            //     yield return 0;
            // }
        }


        // public static IEnumerator PlayAttack(BaseUnit source, AttackActionResult[] res) {
        //     if (res is not {Length: > 0}) yield break;
        //     var playTarget = res[0].Request.Target;
        //
        //
        //     yield return source.PlaySequence(new AttackGestureSequence(playTarget,
        //         () => {
        //             if (!source) {
        //                 return;
        //             }
        //
        //             foreach (var args in res) {
        //                 Global.Get<BattleSystem>().Level.StartCoroutine(
        //                     HandleAttackProcess(source, args.Request.Target, args, null));
        //             }
        //         }));
        // }


        // private static IEnumerator HandleAttackProcess(BaseUnit source, BaseUnit target, AttackActionResult res,
        //     Action                                              afterHit) {
        //     yield return HandleAttack(source, target, res);
        //     afterHit?.Invoke();
        // }


        public static IEnumerator HandleNoSourceDamage(BaseUnit target, DamageInfo info)
        {
            Global.SendEvent(new UnitNoSourceDamageEvent(target, info));

            var armor = target.ComEquip.GetArmor();
            if (armor == null)
            {
                yield return HandleHealthLost(target, info);
            }
            else
            {
                armor.Damage(info.Num);
            }

            yield return target.PlaySequence<DeathGestureSequence>();
        }


        /// <summary>
        /// 处理生命流失
        /// </summary>
        public static IEnumerator HandleHealthLost(BaseUnit target, DamageInfo damage)
        {
            if (damage.Num <= 0) yield break;

            // // 如果单位死亡，则提前判定。等待死亡动画播放结束。
            // // 因为当修改单位剩余生命值时，如果生命值小于0，则会触发单位死亡并播放死亡动画。
            // // 此时会与单位受击动画冲突，导致动画播放异常
            // var health = target.RawStat()[StatField.CurHealth] - damage.Num;
            target.ReceiveDamage(damage.Num);
            Global.SendEvent(new UnitHealthLostEvent(target, damage));
            //
            // // ============================= 播放动画 ============================
            if (target.CurHealth.Value <= 0)
            {
                // if (!target.BuffHolder.HasBuff<UnyieldingEffect>()) {
                //     // 设置生命值
                //     target.RawStat()[StatField.CurHealth] = health;
                //     // 播放死亡动画
                //     yield break;
                // }
                //

                yield return HandleUnitDeath(target);
                // target.BuffHolder.GetBuff<UnyieldingEffect>().Consume();
                // health = 1;
            }
            //
            //
            //
            // target.CurH = health;
        }

        // /// <summary>
        // /// 判断当某单位生命值减少damage点时，是否会死亡
        // /// </summary>
        // public static bool JudgeUnitDeath(BaseUnit unit, int healthDamage) {
        //     return unit.CurStatInt(StatField.CurHealth) <= healthDamage && unit.BuffHolder.HasBuff<UnyieldingEffect>();
        // }


        public static void HandleUnitKill(BaseUnit killer, BaseUnit death)
        {
            HandleUnitKillMoral(killer, death);
        }


        public static IEnumerator HandleUnitDeath(BaseUnit unit)
        {
            yield return Global.Get<BattleSystem>().DestroyUnit(unit);
        }


        public static bool IsUnitDestroyed(BaseUnit unit)
        {
            return Global.Get<BattleSystem>().IsUnitDestroyed(unit);
        }

        #endregion


        #region Morale

        /// <summary>
        /// 处理在进攻之后，士气值的变化
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <param name="res"></param>
        private static IEnumerator HandleAttackMorale(BaseUnit source, BaseUnit target, AttackActionResult res)
        {
            // 被造成的伤害*10%（结算完所有抗性和减伤后）+被造成伤害/该单位的总血量（护甲值+生命值）上限*士气上限。
            var amount = res.MoraleDamage;

            // // Debug.Log("士气伤害: " + amount);
            // if (MoraleReduce(target, amount)) {
            //     // 如果陷入 “士气崩溃” 状态，两单位士气减少;
            //     // yield return MoraleReduceProcess(target);
            // }
            yield break;


            // IEnumerator MoraleReduceProcess(BaseUnit unit) {
            //     if (unit == null) yield break;
            //     // 士气减少 20 点
            //     if (unit != target && !MoraleReduce(unit, 20)) {
            //         yield break;
            //     }
            //
            //     yield return new WaitForSeconds(.4f);
            //     var l = CellGridSystem.Instance.PlaceHolder.GetUnit(unit.Side, unit.CurrentCell.Index + 1);
            //     var r = CellGridSystem.Instance.PlaceHolder.GetUnit(unit.Side, unit.CurrentCell.Index - 1);
            //
            //     yield return SkillTask.Sequence()
            //         .Add(() => MoraleReduceProcess(l))
            //         .Add(() => MoraleReduceProcess(r))
            //         .All();
            // }
        }


        /// <summary>
        /// 单位被击杀时的士气变化
        /// </summary>
        private static void HandleUnitKillMoral(BaseUnit killer, BaseUnit target)
        {
            // 当一次攻击杀死一个单位的一个友方单位时，该单位的士气减少20点。
            // foreach (var unit in CellGridSystem.Instance.PlaceHolder.GetUnitsBySide(target.Side)) {
            //     MoraleReduce(unit, 20);
            // }

            //   当1个单位杀死1个敌方单位时，该单位额外回复20点士气。
            MoraleGrow(killer, 20);
        }


        /// <summary>
        /// 减少单位士气
        /// </summary>
        /// <returns> 该单位是否因为此次士气减少陷入士气崩溃状态 </returns>
        public static bool MoraleReduce(BaseUnit unit, int amount)
        {
            // // 士气减少
            // // 如果该单位含有 "心理免疫", 免疫士气伤害
            // if (unit.ComBuff.HasBuff<BraveMindEffectBuff>()) {
            //     return false;
            // }
            //
            // unit.ComCost.ReduceResource(CostField.Morale, amount);
            // // 如果单位士气归零，则陷入“士气崩溃”状态
            // if (unit.ComCost.GetResource(CostField.Morale) <= 0 && !unit.ComBuff.HasBuff<MoralePanicBuff>()) {
            //     unit.AddBuff(new MoralePanicBuff());
            //     return true;
            // }

            return false;
        }

        /// 增长单位士气
        public static void MoraleGrow(BaseUnit unit, int amount)
        {
            unit.ComCost.AddResource(CostField.Morale, amount);


            // 当士气回满时，移除“士气崩溃”效果
            if (unit.ComCost.GetResource(CostField.Morale) == unit.ComCost.GetMaxValue(CostField.Morale))
            {
                // unit.ComBuff.RemoveBuff<MoralePanicBuff>();
            }
        }

        public static void MoraleGrow(BaseUnit unit, float percent)
        {
            var max = unit.ComCost.GetMaxValue(CostField.Morale);
            MoraleGrow(unit, Mathf.CeilToInt(max * percent));
        }


        /// <summary>
        /// 单位士气最小值为0。如果有“永不言败”效果，则为1
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static int CalMinMorale(BaseUnit unit)
        {
            // return unit.ComBuff.HasBuff<NeverSayNeverEffect>() ? 1 : 0;
            return 1;
        }

        #endregion


        #region Rules

        /// <summary>
        /// 用于处理护盾和穿透机制，判断攻击是否能够穿透护盾，并进行穿透处理
        /// </summary>
        public static bool HandleBrokeThrough(BaseUnit unit, ConfigWeapon equip)
        {
            // // 如果装备不为远程武器，则无法穿透
            // if (equip.GetWeaponType() is not RangedBaseWeaponType weapon)
            //     return false;
            return false;
        }


        public static bool CanUnitPerform(BaseUnit unit)
        {
            // return !unit.ComBuff.HasBuff<MoralePanicBuff>();
            return true;
        }


        public static int GetArmorBreakCount(SkillEntity entity)
        {
            return (entity is not IArmorBreakSkill abs ? 1 : abs.BreakCount());
        }


        /// <summary>
        /// 判断某技能在其他机制影响下是否能够使用
        /// </summary>
        /// <param name="skill"></param>
        /// <returns></returns>
        public static DisableReason CanSkillPerform(SkillEntity skill)
        {
            // 检查状态
            // var head = DisableReason
                // .Build(DS_Reason.Freeze, () => true);
            // head.And(DS_Reason.Panic, () => skill.UnitReference.BuffHolder.HasBuff<MoralePanicBuff>());
            return DisableReason.True();
        }


        /// <summary>
        /// 判断某个单位是否满足成为“偷袭”目标条件
        /// 1.对方身后1格内不存在友军。2.处于士气崩溃中。3.没有护甲值
        /// </summary>
        public static bool CanBeAmbush(BaseUnit unit)
        {
            if (unit == null) return false;

            // //对方身后1格内不存在友军
            // if (CellGridSystem.Instance.PlaceHolder.GetBehindUnit(unit) == null &&
            //     // CellGridSystem.Instance.PlaceHolder.GetBehindCell(unit.CurrentCell) != null) {
            //     return true;
            // }

            // // 处于“士气崩溃中”
            // if (unit.ComBuff.HasBuff<MoralePanicBuff>()) {
            //     return true;
            // }

            // 没有护甲值
            if (!unit.ComEquip.HasArmor())
            {
                return true;
            }

            return false;
        }


        public static void StunShock(BaseUnit target)
        {
            Global.Get<GridBattleGUISystem>().PlayFloatingText(target, "失能");
            target.ComCost.ReduceResource(CostField.ActionTime);
            target.ComCost.ReduceResource(CostField.Reaction);
        }

        /// <summary>
        /// 获得一个单位的过载点数
        /// </summary>
        /// <returns></returns>
        public static int GetOverload(BaseUnit unit)
        {
            return Math.Max(0, -unit.ComCost.GetResource(CostField.MagicPoint));
        }


        /// <summary>
        /// 消除一个单位的所有过载点数
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static int ClearOverload(BaseUnit unit)
        {
            var point = GetOverload(unit);
            unit.ComCost.AddResource(CostField.MagicPoint, point);
            return point;
        }


        public static void HealUnit(BaseUnit unit)
        {
            if (unit == null) return;

            // unit.SetStatValue(StatField.CurHealth, unit.CurStatValue(StatField.MaxHealth));
            foreach (var armor in unit.ComEquip.AllArmor())
            {
                armor.Repair();
            }
        }


        public static void RepairArmor(BaseUnit unit, int amount)
        {
            var armors = unit.ComEquip.AllArmor();
            armors.Reverse();

            foreach (var armor in armors.Where(x => x is {IsShieldFragment: false}))
            {
                if (amount == 0) break;
                if (armor.IsUnDamaged)
                {
                    continue;
                }

                amount--;
                armor.Repair();
            }
        }

        #endregion


        // 触发反应
        public static IEnumerator CallReaction<T>(T args) where T : ReactionArgs
        {
            var model = Global.Get<BattleSystem>().BattleSettle;


            // // 获得注册的反应 
            // var reactions
            //     = model.ReactionArgs.Where(i => i.ArgsType == typeof(T))
            //         .Select(i => i as ReactionEventWrapper<T>)
            //         .ToList();
            //
            //
            // // 玩家优先选择反应
            // yield return model.HumanPlayer
            //     .ResolveReaction(GetWrapperByPlayer(model.HumanPlayer), args);
            // yield return model.AIPlayer
            //     .ResolveReaction(GetWrapperByPlayer(model.AIPlayer), args);
            //
            //
            // List<ReactionEventWrapper<T>> GetWrapperByPlayer(Player player)
            //     => reactions.Where(x => x.Register.PlayerNumber == player.PlayerNumber).ToList();
            yield break;
        }

        public static IEnumerator OnCallOption(SkillEntity skill, IEnumerable<OptionItem> args)
        {
            return Global.Get<BattleSystem>().BattleSettle.CurrentPlayer.ResolveOption(skill, args);
        }
    }
}